import characterTools from "shared/component/common/characterTools";
import common from "shared/component/common/common";
import rMath from "shared/component/common/rMath";
import { stickDirection, stickTools } from "shared/component/common/stickTools";
import { ContainerService } from "shared/component/container/ContainerService";
import EventBinder from "shared/component/event/EventBinder";
import InstanceMap from "shared/component/event/InstanceRemoveEvent";
import Log4R from "shared/component/log/Log4R";
import { setTimeOut } from "shared/component/time/SetTime";
import WallHeader from "shared/component/trigger/WallHeader";

import { CharacterState } from "shared/enums/CharacterState";
import { ColiGroup } from "shared/enums/ColiGroup";
const loginfo = Log4R.getLog('info');
/** 运动状态 */
class MoveStates implements Ctn.move.MoveState {
    orientation: Vector3 = rMath.vectors.v0
    /** 运动方向 */
    vector?: Vector3
    /** 可以改变速度 */
    changeSpeedEnable = true
    moveConfig?: Ctn.move.MoveConfig
    /** 是否可以移动 */
    moveEnable = true
    /** 是否可以跳跃 */
    jumpEnable = true

    turnEnable?: boolean

    constructor(character: Ctn.character.HumanModel) {

    }
    dodgeEnable = true;
}
export class Move2DServiceImpl extends ContainerService<Ctn.Move2DService, Ctn.Move2DEntity> implements Ctn.Move2DService {
    /** 物理上的停顿 */
    pause(characterEntity: Ctn.character.CharacterEntity, pauseEntity: TimeComponent.PauseEntity) {
        if (!characterEntity.character) return
        if (pauseEntity.pause) {
            characterEntity.character.HumanoidRootPart.Anchored = true
        } else {
            characterEntity.character.HumanoidRootPart.Anchored = false
        }
    }
    protected serverCalls: (keyof this)[] = [];
    protected serviceName: keyof Ctn.Services = "move2DService";

    /** 玩家移动方向纠正 */
    private playerVectorModify?: Vector3Value;
    /** 角色默认质量 */
    protected defaultMass?: NumberValue;
    /** 获取state */
    private getState(character: Model) {
        const characterEntity = this.getCharacter(character);
        return characterEntity?.moveState

    }
    public hot(): void {
        this.scanHot(script);
    }
    /** 添加角色 */
    public addCharacter(moveConfig: Ctn.move.MoveConfig) {
        const characterEntity = this.getCharacter(moveConfig.humanModel);
        if (!characterEntity) return
        /** 角色移动状态 */
        const states = new MoveStates(moveConfig.humanModel);
        // moveConfig.humanModel.Humanoid.SetStateEnabled(Enum.HumanoidStateType.Climbing, false)
        // loginfo?.info('character state', moveConfig.humanModel, moveConfig.humanModel.Humanoid.GetStateEnabled(Enum.HumanoidStateType.Climbing))
        states.moveConfig = moveConfig;

        characterEntity.moveState = states
    }
    /** 设置是否可移动 */
    public setCtrlEnable(character: Ctn.character.HumanModel, enable: boolean) {

        const state = this.getState(character)

        if (state) {
            if (state.changeSpeedEnable === enable) {
                return
            }
            state.changeSpeedEnable = enable
            if (enable) {
                this.changeSpeed(character, state.moveConfig?.walkSpeed || 16)
                this.orientationWalkDirection(character)
            } else {
                character.Humanoid.WalkSpeed = 0
            }
        }

    }
    /** 设置是否可移动 */
    public setTurnEnable(character: Ctn.character.HumanModel, enable: boolean) {
        const state = this.getState(character)
        if (state) {
            state.turnEnable = enable
        }
        if (enable) {
            this.orientationWalkDirection(character)
        }
    }
    /** 设置是否可跳跃 */
    public setJumpEnable(character: Ctn.character.HumanModel, enable: boolean) {
        const state = this.getState(character)
        if (state) {
            state.jumpEnable = enable
        }
    }
    /** 设置是否可翻滚 */
    public setDodgeEnable(character: Ctn.character.HumanModel, enable: boolean) {
        const state = this.getState(character)
        if (state) {
            state.dodgeEnable = enable
        }
    }
    /** 设置运动方向 */
    private orientationWalkDirection(humanModel: Ctn.character.HumanModel) {
        const states = this.getState(humanModel)
        if (states?.vector) {
            if (states?.vector.X !== 0) {
                states.orientation = new Vector3(states?.vector.X, 0, 0)
                const targetCframe = new CFrame(rMath.vectors.v0, new Vector3(states?.vector.X, 0, 0))
                let alignOrientation = humanModel.HumanoidRootPart.AlignOrientation;
                if (alignOrientation.CFrame !== targetCframe) {
                    task.spawn(() => {
                        alignOrientation.CFrame = new CFrame()
                        task.wait(0.001)
                        alignOrientation.CFrame = targetCframe
                    })
                }

            }
            this.changeSpeed(humanModel, states.moveConfig?.walkSpeed || 16)
        }

    }
    /**
     * 角色状态变更
     */
    private moveControlChangeEventBinder = new EventBinder<(character: Ctn.character.HumanModel, control: Vector3) => void>()
    private actController?: Ctn.move.ActController
    /**
     * 状态改变
     */
    onMoveControlChange = this.moveControlChangeEventBinder.bind()

    private stateChangeBinder = new EventBinder<(character: Ctn.character.HumanModel, state: CharacterState) => void>()
    /** 状态改变广播 */
    onStateChangeChange = this.stateChangeBinder.bind()
    /** 移动角色 */
    public move(vector: Vector3, humanModel: Ctn.character.HumanModel) {
        /** 忽略操作 */
        let moveControl = vector;
        let ignore = false
        if (vector.Magnitude === 1) {
            moveControl = vector.Unit
        } else if (vector.Magnitude > 0.7) {
            moveControl = vector.Unit
        } else if (vector.Magnitude === 0) {
            moveControl = rMath.vectors.v0;
        } else {
            ignore = true
        }
        if (!ignore)
            this.moveControlChangeEventBinder.callBack(humanModel, moveControl)
        const states = this.getState(humanModel)
        if (states) {

            // loginfo?.info('move vector', vector, states)
            if (states.moveEnable) {

                if (vector.Magnitude === 0) {
                    humanModel.Humanoid.Move(vector)
                    this.changeSpeed(humanModel, 0)
                } else if (vector.Magnitude === 1) {
                    vector = vector.Unit
                    humanModel.Humanoid.Move(vector)
                } else if (vector.Magnitude > 0.7) {
                    vector = vector.Unit
                    humanModel.Humanoid.Move(vector)
                } else {
                    return
                }
                states.vector = vector;
                if (states.changeSpeedEnable) {
                    if (vector.Magnitude !== 0 && states.turnEnable) {
                        this.orientationWalkDirection(humanModel)
                    }
                    this.changeSpeed(humanModel, states.moveConfig?.walkSpeed || 16)
                }
            }
        }

    }
    private changeSpeed(humanModel: Ctn.character.HumanModel, speed: Number) {
        const states = this.getState(humanModel)
        if (states?.changeSpeedEnable) {
            humanModel.Humanoid.WalkSpeed = states.moveConfig?.walkSpeed || 16
        }
    }
    /**
     * 移动玩家角色
     * @param vector 摇杆向量
     * @param degree 摇杆角度
     */
    public movePlayer(vector: Vector3, degree: number) {


        const localCharacter = game.GetService('Players').LocalPlayer.Character as Ctn.character.HumanModel;
        if (localCharacter) {
            if (stickTools.getDirection(degree) === stickDirection.down) {
                this.move(rMath.vectors.v0, localCharacter);
            } else {
                const vectorModify = this.playerVectorModify?.Value;
                if (vectorModify) {
                    vector = vector.mul(vectorModify)
                }
                // loginfo?.info('movePlayer', vector)
                this.move(vector, localCharacter);
            }
            // vector = new Vector3(vector.X, vector.Z, 0)

        }
    }
    /** 移动玩家角色 */
    public actPlayer(act: Ctn.character.ActEntity) {
        const localCharacter = game.GetService('Players').LocalPlayer.Character as Ctn.character.HumanModel;
        if (localCharacter) {
            this.act(act, localCharacter);
        }
    }
    public act(act: Ctn.character.ActEntity, humanModel: Ctn.character.HumanModel) {
        const characterEntity = this.getCharacter(humanModel);
        if (!characterEntity) return
        const states = this.getState(humanModel)
        if (!states) {


            // loginfo?.info('characterEntity', humanModel, characterEntity, this.getInstanceMap())
            throw ('no states:' + humanModel)
        }
        // loginfo?.info("act", states)

        switch (act.act) {

            case 'move':
                if (states.moveEnable) {
                    this.move(act.vector || humanModel.HumanoidRootPart.CFrame.VectorToWorldSpace(
                        new Vector3(0, 0, -1)
                    ), humanModel)
                }
                break;
            // case 'dodge':
            //     if (characterEntity.humanStates?.actStates === CharacterState.WallHeaderClimb) {
            //         return
            //     }
            //     if (states.dodgeEnable) {
            //         if (act.enable) {
            //             /** 逻辑转向 */
            //             const logicCframe = characterTools.getCharacterLogicCframe(characterEntity)

            //             if (this.actController?.dodge(characterEntity, act.enable)) {
            //                 this.stateChangeBinder.callBack(humanModel, CharacterState.Dodge)
            //             }
            //         } else {
            //             // this.actController?.jump(characterEntity, act.enable)
            //         }
            //     }
            //     break;
            case 'jump':
                if (characterEntity.humanStates?.actStates === CharacterState.WallHeaderClimb) {
                    return
                }

                if (states.jumpEnable) {
                    // humanModel.Humanoid.Jump = act.enable

                    if (act.enable) {
                        if (stickTools.getDirection(characterEntity.humanStates?.ctrlDegree) === stickDirection.down) {

                        } else {
                            // loginfo?.info('jumpTimes', characterEntity.jumpTimes)
                            if (characterEntity.jumpTimes >= (characterEntity.maxJumpTimes || 2)) {
                                return
                            }
                            this.stateChangeBinder.callBack(humanModel, CharacterState.Jumping)
                            this.actController?.jump(characterEntity, act.enable)
                            characterEntity.jumpTimes++

                        }
                    } else {
                        this.actController?.jump(characterEntity, act.enable)
                    }

                }
                break;
            case 'anchored'://钉固
                if (humanModel.PrimaryPart) {

                    // states.alignPosition.Enabled = act.enable;
                    if (act.enable) {
                        // states.alignPosition.RigidityEnabled = true;
                        // states.alignPosition.Position = act.cframe?.Position || humanModel.PrimaryPart?.CFrame.Position
                        // states.alignOrientation.CFrame = act.cframe || humanModel.PrimaryPart?.CFrame
                        humanModel.Humanoid.WalkSpeed = 0;
                        humanModel.PrimaryPart.CFrame = act.cframe || humanModel.PrimaryPart?.CFrame
                    }
                    humanModel.PrimaryPart.Anchored = act.enable;
                }
                break;

        }
    }
    public init(): void {
        this.playerVectorModify = this.getConfig('playerVectorModify', 'Vector3Value');

        this.defaultMass = this.getConfig('defaultMass', 'NumberValue');
    }

    private catchControlller?: Ctn.move.CatchControlller
    /**
     * 重置力
     * @param character 
     */
    public resetForce(character: Ctn.character.HumanModel) {
        character.Trail.CatchController.Enabled = false;
    }
    /** 改变碰撞组 */
    public changeColli(state: CharacterState, character: Ctn.character.HumanModel) {
        const characterEntity = this.getInstanceMap().get(character);
        if (!characterEntity) return
        this.actController?.changeColli(state, characterEntity)
    }
    /**
     * 触发机关
     * @param trigger 
     * @param toucher 
     * @returns 
     */
    public touchTrigger(trigger: clazz.TriggerBase, toucher: BasePart) {
        const humanModel = toucher.FindFirstAncestorOfClass('Model');
        if (!humanModel) return
        const characterEntity = this.getCharacter(humanModel);
        if (!characterEntity) return
        if (trigger.IsA('WallHeader')) {
            this.catchControlller?.catchByTrail(characterEntity, {
                att: trigger.catchAttachment
            })
        }
    }
}